/**
 * Server
 * 
 */
package br.ufal.ic.sd.project.server.core;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MulticastSocket;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.Vector;

import br.ufal.ic.sd.project.server.exception.ServerException;
import br.ufal.ic.sd.project.server.singleton.ServerToken;
import br.ufal.ic.sd.project.server.singleton.Token;


/**
 * @author keven lenisk almeida andrade
 *
 */
public abstract class Server implements ServerManager{
	
	protected Channel objChannel;
	
	protected ServerToken objServerTokken;
	
	protected String strRepository;
	
	protected TokenListener objTokenListener;
	
	protected Collection<ServerService> services;
	
	
	//=========================================================== Getters and Setters =========================================================
	
	/**
	 * @return the objChannel
	 */
	public Channel getObjChannel() {
	    return objChannel;
	}

	/**
	 * @param objChannel the objChannel to set
	 */
	public void setObjChannel(Channel objChannel) {
	    this.objChannel = objChannel;
	}
	
	/**
	 * @return the strRepository
	 */
	public String getStrRepository() {
	    return strRepository;
	}

	/**
	 * @param strRepository the strRepository to set
	 */
	public void setStrRepository(String strRepository) {
	    this.strRepository = strRepository;
	}
	
	/**
	 * @return the objServerTokken
	 */
	public ServerToken getObjServerTokken() {
	    return objServerTokken;
	}

	/**
	 * @param objServerTokken the objServerTokken to set
	 */
	public void setObjServerTokken(ServerToken objServerTokken) {
	    this.objServerTokken = objServerTokken;
	}
	
	/**
	 * @return the objTokenListener
	 */
	public TokenListener getObjTokenListener() {
	    return objTokenListener;
	}

	/**
	 * @param objTokenListener the objTokenListener to set
	 */
	public void setObjTokenListener(TokenListener objTokenListener) {
	    this.objTokenListener = objTokenListener;
	}
	
	
	
	
	//================================================================== Methods ===============================================================

	/**
	 * @return the services
	 */
	public Collection<ServerService> getServices() {
	    return services;
	}

	/**
	 * @param services the services to set
	 */
	public void setServices(Collection<ServerService> services) {
	    this.services = services;
	}

	public abstract void testeDeCarga();
	
	/**
	 *@Method that read a sequence of bytes from the channel
	 */
	public int read(byte[] bytes) {
		
		try {
			
			return this.objChannel.getObjInputStreamIn().read(bytes);

		} catch (IOException e) {
//			System.err.println(e.getMessage());
		    System.err.println("Falha do sistema!");
		}

		return -1;
	}

	/**
	 *@Method that read an object from the channel
	 *@return null in case of error
	 */
	public String read() {
		
		try {
			return this.objChannel.getObjInputStreamIn().readObject().toString();
			
		} catch (IOException e) {
		    System.err.println("Falha do sistema!");
		    e.printStackTrace();
		} catch (ClassNotFoundException e) {
		    System.err.println("Falha do sistema!");
		    e.printStackTrace();
		} 
		return null;
		
	}

	/**
	 *@Method that push a sequence bytes throw the communication channel 
	 */
	public void write(byte[] bytes, int i) {

		try {
			
			this.objChannel.getObjOutputStreamOut().write(bytes, 0, i);
			this.objChannel.getObjOutputStreamOut().flush();

		} catch (IOException e) {
//			System.err.println(e.getMessage());
		    System.err.println("Falha do sistema!");
		}
	}

	/**
	 *@Method that push a message throw the communication channel 
	 */
	public void write(String strMessage) {

		try {
			this.objChannel.getObjOutputStreamOut().writeObject(strMessage);
			this.objChannel.getObjOutputStreamOut().flush();

		} catch (IOException e) {
//			System.err.println(e.);
		    System.err.println("Falha do sistema!");
		}
	}
	
	public String readBytes(){
	    
            Integer b;
            Vector<Byte> stream = new Vector<Byte>();
            try {
		while ((b = this.objChannel.getObjInputStreamIn().read()) != -1) {
		    stream.add(b.byteValue());
		}
	    } catch (IOException e) {
		e.printStackTrace();
	    }
            
            byte[] streamArray = new byte[stream.size()];
            for (int i = 0; i < stream.size(); i++) {
                streamArray[i] = stream.get(i);
            }
            
            return new String(streamArray);
	    
	}

	public void setTokenStateOn() {
	    this.objServerTokken.setBooPermisson(true);
	    System.out.println(this.objServerTokken.getBooPermisson());
	}
	
	public void setTokenStateOff() {
	    this.objServerTokken.setBooPermisson(false);
	    System.out.println(this.objServerTokken.getBooPermisson());
	}
}
